<?php

define('LOG_LEVEL_DEBUG', 10);
define('LOG_LEVEL_INFO', 20);
define('LOG_LEVEL_WARN', 30);
define('LOG_LEVEL_ERROR', 40);

class log_Logger {
    // log_method can be 'echo', 'file' or 'div'
    private $log_method = 'echo';
    private $suppress_paths = array();
    private $buffer = '';
    private $filefd = false;

    public $buffer_output = false;
    public $log_level = LOG_LEVEL_INFO;

    function log_debug() {
        if ($this->log_level > LOG_LEVEL_DEBUG) {
            return;
        }

        $args = func_get_args();

        $path = array_shift($args);
        $msg = array_shift($args);

        $this->log($path, 'debug', $msg, $args);
    }

    function log_info() {
        if ($this->log_level > LOG_LEVEL_INFO) {
            return;
        }
        
        $args = func_get_args();

        $path = array_shift($args);
        $msg = array_shift($args);

        $this->log($path, 'info', $msg, $args);
    }

    function log_warn() {
        if ($this->log_level > LOG_LEVEL_WARN) {
            return;
        }

        $args = func_get_args();

        $path = array_shift($args);
        $msg = array_shift($args);

        $this->log($path, 'warn', $msg, $args);
    }

    function log_error() {
        if ($this->log_level > LOG_LEVEL_ERROR) {
            return;
        }

        $args = func_get_args();

        $path = array_shift($args);
        $msg = array_shift($args);

        $this->log($path, 'error', $msg, $args);
    }

    function log($path, $level, $msg, $args) {
        if (! $this->path_is_enabled($path)) {
            return;
        }
        
        $out = "$path\t$level\t" . $this->format($msg, $args) . "\n";
        if ($this->buffer_output) {
            $this->buffer .= $out;
        } else {
            $this->output($out);
        }
    }

    function output($txt) {
        switch ($this->log_method) {
        case 'echo':
            echo $txt;
            break;
        case 'file':
            // XXX/bowei
            break;
        case 'div':
            // XXX/bowei
            break;
        }
    }

    function flush() {
        $this->output($buffer);
        $this->buffer = '';
    }

    function path_is_enabled($path) {
        foreach ($this->suppress_paths as $p) {
            if (preg_match($p, $path)) {
                return false;
            }
        }
        return true;
    }

    function format($str, $args) {
        while (true) {
            $obj = array_shift($args);
            if ($obj == NULL) {
                break;
            }
            $obj_str = var_export($obj, true);
            $new_str = preg_replace('/%O/', $obj_str, $str, 1);

            if ($str == $new_str) {
                break;
            }
            $str = $new_str;
        }
        return $str;
    }
}

?>
